import pdfplumber
import fitz
import os

def detect_label_bboxes(pdf_path):
    """ 检测所有标签的边界框坐标，并去除空白部分 """
    bboxes = []  # 用于存储每个标签的边界框
    padding = 10  # 设置边距为10px
    
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            # 提取页面上的所有矩形和文本
            rects = page.rects
            texts = page.extract_words()
            # print(texts)
            
            # 检查是否包含"请不要遮住此标签"文本
            has_cover_text = any('请不要遮住此标签' in text['text'] for text in texts)
            
            if has_cover_text:
                # 第二种方式：从"Logística"到"请不要遮住此标签"
                # print("使用第二种裁剪方式：从Logística到请不要遮住此标签")
                
                # 找到所有"Logística"文本和"请不要遮住此标签"文本
                mudi_texts = []
                logistica_texts = []
                cover_texts = []
                mixtos_texts = []
                
                for i, text in enumerate(texts):
                    if '目的地' in text['text']:
                        mudi_texts.append(text)
                    if '纸箱编号' in text['text']:
                        logistica_texts.append(text)
                    if '请不要遮住此标签' in text['text']:
                        cover_texts.append(text)
                    if 'mixtos' in text['text']:
                        mixtos_texts.append(text)

                print(len(logistica_texts))
                print(len(cover_texts))
                if logistica_texts and cover_texts and mixtos_texts:
                    logistica_texts.append(text)
                    # 为每个标签创建边界框
                    for i in range(min(len(logistica_texts), len(cover_texts))):
                        logistica_text = logistica_texts[i]
                        cover_text = cover_texts[i]
                        mixtos_text = mixtos_texts[i]
                        mudi_text = mudi_texts[i]

                        # 使用Logística的top作为min_y，请不要遮住此标签的bottom作为max_y
                        min_y = logistica_text['top']
                        max_y = cover_text['bottom']
                        # print(logistica_text)
                        # 计算左右边界
                        min_x = mudi_text['x0']
                        max_x = mixtos_text['x1']
                        print("min_x, max_x, min_y, max_y")
                        print(min_x,max_x,min_y,max_y)
                        
                        # for text in texts:
                        #     # 只考虑在y范围内的文本，包括边界
                        #     if min_y <= text['top'] <= max_y or min_y <= text['bottom'] <= max_y:
                        #         min_x = min(min_x, text['x0'])
                        #         max_x = max(max_x, text['x1'])
                        
                        # 确保包含Logística文本本身
                        # min_x = min(min_x, logistica_text['x0'])
                        # max_x = max(max_x, logistica_text['x1'])
                        
                        # 添加padding
                        min_x = max(0, min_x - padding)
                        min_y = max(0, min_y - padding)
                        max_x = min(page.width, max_x + padding)
                        max_y = min(page.height, max_y + padding)
                        
                        bbox = (min_x, min_y, max_x, max_y)
                        bboxes.append((page.page_number, bbox))
                        print(f"检测到标签 {i+1}: 从 x={min_x:.1f} 到 x={max_x:.1f},从 y={min_y:.1f} 到 y={max_y:.1f}")
                else:
                    # 如果找不到关键文本，使用默认方式
                    # print("未找到关键文本，使用默认裁剪方式")
                    bbox = get_default_bbox(page, texts, padding)
                    bboxes.append((page.page_number, bbox))
            else:
                # 第一种方式：使用所有文本的边界
                print("使用第一种裁剪方式：所有文本边界")
                bbox = get_default_bbox(page, texts, padding)
                bboxes.append((page.page_number, bbox))
    
    return bboxes

def get_default_bbox(page, texts, padding):
    """ 获取默认的边界框 """
    # 初始化边界值
    min_x = float('inf')
    min_y = float('inf')
    max_x = float('-inf')
    max_y = float('-inf')
    
    # 检查所有文本的边界
    for text in texts:
        min_x = min(min_x, text['x0'])
        min_y = min(min_y, text['top'])
        max_x = max(max_x, text['x1'])
        max_y = max(max_y, text['bottom'])
    
    # 添加padding（确保不超出页面边界）
    min_x = max(0, min_x - padding)
    min_y = max(0, min_y - padding)
    max_x = min(page.width, max_x + padding)
    max_y = min(page.height, max_y + padding)
    
    return (min_x, min_y, max_x, max_y)

def amazon_crop_and_save(pdf_path, output_file="output.pdf"):
    doc = fitz.open(pdf_path)  # 打开PDF文档
    bboxes = detect_label_bboxes(pdf_path)  # 检测标签边界框

     # 检查bboxes是否为空
    if not bboxes:
        doc.close()  # 关闭文档
        raise ValueError("该文件可处理内容为空，未检测到任何可裁剪的标签")
    
    # 创建一个新的PDF文档用于保存所有裁剪后的页面
    output_doc = fitz.open()
    
    for idx, (page_num, bbox) in enumerate(bboxes, 1):
        # 获取当前页面
        page = doc[page_num - 1]
        # 创建一个矩形对象，表示裁剪区域
        rect = fitz.Rect(bbox[0], bbox[1], bbox[2], bbox[3])
        
        # 在新文档中创建一个新页面，大小与裁剪区域相同
        new_page = output_doc.new_page(width=rect.width, height=rect.height)
        
        # 将原始页面的裁剪区域绘制到新页面上
        new_page.show_pdf_page(
            fitz.Rect(0, 0, rect.width, rect.height),  # 新页面的矩形区域
            doc,  # 原始文档
            page_num - 1,  # 原始页面编号
            clip=rect,  # 裁剪区域
        )
    
    # 保存所有裁剪后的页面为一个新的PDF文件
    output_doc.save(output_file)
    output_doc.close()  # 关闭新文档

def add_summary_page(pdf_path, shipping_id, shipments, total_boxes, warehouse, date=None):
    """
    为PDF添加一个总结页面，字体加粗，Total、Fecha 和 Almacén 三行显示在PDF最下方
    货件信息每行显示两个
    
    参数:
    - pdf_path: PDF文件路径
    - shipping_id: 送仓单号
    - shipments: 货件信息数组，每个元素包含 tracking_number 和 begin end
    - total_boxes: 总箱数
    - warehouse: 仓库信息
    - date: 日期
    """
    # 打开PDF
    doc = fitz.open(pdf_path)
    
    # 创建新页面 (宽度15.2cm, 高度10.4cm, 转换为点)
    width = 15.2 * 28.35  # 厘米转点
    height = 10.4 * 28.35  # 厘米转点
    page = doc.new_page(-1, width=width, height=height)
    
    # 设置字体和格式 - 加大加粗
    title_font_size = 20  # 标题字体大小
    content_font_size = 12  # 内容字体大小
    text_color = (0, 0, 0)  # 黑色
    
    # 计算文本位置
    margin_top = 30
    margin_left = 20
    line_height = 24
    right_margin = width - 50  # 右边距，用于右对齐
    mid_point = width / 2  # 页面中点，用于分隔左右两个货件信息
    
    # 计算页面底部位置，留出三行文本的空间
    bottom_margin = height - 20
    bottom_line_3 = bottom_margin - line_height * 2  # Almacén
    bottom_line_2 = bottom_margin - line_height * 1  # Fecha
    bottom_line_1 = bottom_margin  # Total
    
    # 添加送仓单号 (加粗)
    page.insert_text(
        (margin_left, margin_top), 
        f"Envío: {shipping_id}", 
        fontsize=title_font_size, 
        color=text_color,
        fontname="Helvetica-Bold"  # 使用粗体字
    )
    
    # 添加货件信息 (每行两个)
    current_y = margin_top + line_height

    # 处理货件信息，每行显示两个
    for i in range(0, len(shipments), 2):
        # 检查当前行是否会与底部三行重叠
        if current_y + line_height >= bottom_line_3 - line_height:
            # 如果会重叠，则不再显示更多货件信息
            break
            
        # 处理左侧货件
        if i < len(shipments):
            shipment = shipments[i]
            tracking_number = shipment.get('tracking_number', '')
            begin = shipment.get('begin', '')
            end = shipment.get('end', '')
            
            # 格式化箱号范围
            box_text = f"#{begin}-{end}"
            
            # 添加左侧货件信息 (加粗)
            page.insert_text(
                (margin_left, current_y), 
                f"{tracking_number} {box_text}", 
                fontsize=title_font_size, 
                color=text_color,
                fontname="Helvetica-Bold"
            )
        
        # 处理右侧货件
        if i + 1 < len(shipments):
            shipment = shipments[i + 1]
            tracking_number = shipment.get('tracking_number', '')
            begin = shipment.get('begin', '')
            end = shipment.get('end', '')
            
            # 格式化箱号范围
            box_text = f"#{begin}-{end}"
            
            # 添加右侧货件信息 (加粗)
            page.insert_text(
                (mid_point + 20, current_y), 
                f"{tracking_number} {box_text}", 
                fontsize=title_font_size, 
                color=text_color,
                fontname="Helvetica-Bold"
            )
        
        # 每处理完一行（两个货件），垂直位置下移
        current_y += line_height

        # 如果shipments超过12个，则在下方增加一行提示：“...（超出12个记录不展示，请在指令详情页面查看）”
    if len(shipments) > 12:
        page.insert_text(
            (margin_left, bottom_line_3 - line_height),
            "..." + "(No se muestran más de 12 registros)",
            fontsize=title_font_size,
            color=text_color,
            fontname="Helvetica-Bold"
        )
    
    # 添加总箱数 (右对齐, 加粗)，放在最下方的一行
    total_text = f"Total: {total_boxes} {'cajas' if int(total_boxes) > 1 else 'caja'}"
    tw = fitz.get_text_length(total_text, fontname="Helvetica-Bold", fontsize=title_font_size)
    page.insert_text(
        (right_margin - tw, bottom_line_3), 
        total_text, 
        fontsize=title_font_size, 
        color=text_color,
        fontname="Helvetica-Bold"
    )
    
    # 添加日期 (右对齐, 加粗)，放在倒数第二行
    current_date = date
    
    fecha_text = f"Fecha: {current_date}"
    tw = fitz.get_text_length(fecha_text, fontname="Helvetica-Bold", fontsize=title_font_size)
    page.insert_text(
        (right_margin - tw, bottom_line_2), 
        fecha_text, 
        fontsize=title_font_size, 
        color=text_color,
        fontname="Helvetica-Bold"
    )
    
    # 添加仓库信息 (右对齐, 加粗)，放在倒数第三行
    almacen_text = f"Almacén: {warehouse}"
    tw = fitz.get_text_length(almacen_text, fontname="Helvetica-Bold", fontsize=title_font_size)
    page.insert_text(
        (right_margin - tw, bottom_line_1), 
        almacen_text, 
        fontsize=title_font_size, 
        color=text_color,
        fontname="Helvetica-Bold"
    )
    
    # 创建一个临时文件路径
    temp_path = pdf_path + ".temp"
    
    # 保存PDF到临时文件
    doc.save(temp_path)
    doc.close()
    
    # 关闭文档后，用临时文件替换原始文件
    if os.path.exists(temp_path):
        os.replace(temp_path, pdf_path)

def amazon_crop_and_save_with_summary(pdf_path, output_file, shipping_id, shipments, total_boxes, warehouse, date=None):
    """
    裁剪PDF并添加总结页
    
    参数:
    - pdf_path: 输入PDF路径
    - output_file: 输出PDF路径
    - shipping_id: 送仓单号
    - shipments: 货件信息数组，每个元素包含 tracking_number 和 begin end
    - total_boxes: 总箱数
    - warehouse: 仓库信息
    - date: 日期，如果为None则使用当前日期
    """
    try:
        # 先执行原有的裁剪功能
        amazon_crop_and_save(pdf_path, output_file)
        
        # 然后添加总结页
        add_summary_page(output_file, shipping_id, shipments, total_boxes, warehouse, date)
        
        return output_file
    except ValueError as e:
        # 重新抛出ValueError异常，保持原始错误信息
        raise ValueError(str(e))
    except Exception as e:
        # 处理其他可能的异常
        raise Exception(f"处理PDF时发生错误: {str(e)}")
    
if __name__ == "__main__":
    amazon_crop_and_save("input.pdf")